package com.olympus.hermes.auth.config;

import com.olympus.hermes.auth.service.ClientService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.util.Arrays;

/**
 * @author Mickey
 * @since 2021/1/30
 */
@Configuration
@AllArgsConstructor
public class TokenGranterConfig {

    private final ClientService clientService;

    private final OAuth2RequestFactory requestFactory;

    private final AuthenticationManager authenticationManager;

    private final JwtTokenStore jwtTokenStore;

    private final JwtAccessTokenConverter jwtAccessTokenConverter;

    @Bean
    public ResourceOwnerPasswordTokenGranter resourceOwnerPasswordTokenGranter() {
        return new ResourceOwnerPasswordTokenGranter(
                authenticationManager,
                defaultTokenServices(),
                clientService,
                requestFactory);
    }

    @Bean
    public ClientCredentialsTokenGranter clientCredentialsTokenGranter() {
        return new ClientCredentialsTokenGranter(
                defaultTokenServices(),
                clientService,
                requestFactory);
    }

    public DefaultTokenServices defaultTokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(jwtTokenStore);
        defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter);
        defaultTokenServices.setClientDetailsService(clientService);
        return defaultTokenServices;
    }

    @Bean
    @Primary
    public CompositeTokenGranter compositeTokenGranter() {
        return new CompositeTokenGranter(Arrays.asList(
                resourceOwnerPasswordTokenGranter(),
                clientCredentialsTokenGranter()
        ));
    }
}
